let logger = require("pomelo-logger").getLogger(__filename);
let DateUtil = require("../../../utils/dateUtil");
let pomelo = require("pomelo");

let Table = function () {
    this.room = null;
    this.tid = "";
    this.code = "";     //code="0" systemTable, code是6位数字串 自建房
    this.gid = 0;
    this.creatorUid = 0;
    this.multiplier = 0;
    this.visible = false;
    this.maxPlayers = 5;
    this.players = [];
    this.playingFlag = 0;
    this.createTime = 0;
    this.lastReadyPlayerTime = 0;
    this.gameStartTime = 0;
};
Table.prototype.getPlayingPlayers = function () {
    let result = [];
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && player.isReady()) {
            result.push(player);
        }
    }
    return result;
};

Table.prototype.getUnreadyPlayers = function () {
    let result = [];
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && !player.isReady()) {
            result.push(player);
        }
    }
    return result;
};

Table.prototype.getAllPlayers = function () {
    let result = [];
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null) {
            result.push(player);
        }
    }
    return result;
};

Table.prototype.getPlayingPlayerByUid = function (uid) {
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && (player.getUid() === uid) && player.isReady()) {
            return player;
        }
    }
    return null;
};

Table.prototype.getFirstPlayingPlayer = function () {
    let playingPlayers = this.getPlayingPlayers();
    if (playingPlayers.length > 0) {
        return playingPlayers[0];
    } else {
        return null;
    }
};

Table.prototype.isFull = function () {
    return this.getNumOfPlayers() >= this.maxPlayers;
};

Table.prototype.isEmpty = function () {
    return this.getNumOfPlayers() === 0;
};

Table.prototype.isAllRobot = function () {
    if (this.isEmpty()) {
        return false;
    }
    for (let player of this.players) {
        if (player != null && player.isRobot === 0) {
            return false;
        }
    }
    return true;
};

Table.prototype.isAllReady = function () {
    return this.getNumOfReadyPlayers() >= this.maxPlayers;
};

Table.prototype.setReady = function (player) {
    if (this.playingFlag >= 1) {
        logger.error("game has been started");
        return false;
    }
    if (player.getBalance() < this.getFee()) {
        return false;
    }
    if (player.getBalance() < this.room.minStack) {
        return false;
    }
    player.setReady();
    this.lastReadyPlayerTime = DateUtil.nowMS();
    return true;
};

Table.prototype.getNumOfReadyPlayers = function () {
    let numOfReadyPlayers = 0;
    this.players.forEach(function (player) {
        if (player == null) {
            return;
        }
        if (player.isReady()) {
            numOfReadyPlayers = numOfReadyPlayers + 1;
        }
    });
    return numOfReadyPlayers;
};

Table.prototype.start = function () {
    this.beforeStart();
    this.lastReadyPlayerTime = 0;
    this.playingFlag = 1;
    this.players.forEach(function (player) {
        if (player != null) {
            player.clearGetReadyCountDown();
            player.resetInTable();
        }
    });
    this.gameStartTime = DateUtil.nowMS();
};

Table.prototype.getTid = function () {
    return this.tid;
};

Table.prototype.getCode = function () {
    return this.code;
};

Table.prototype.isVisible = function () {
    return this.visible;
};

Table.prototype.getRoom = function () {
    return this.room;
};

Table.prototype.getIsPlaying = function () {
    return this.playingFlag > 0;
};

Table.prototype.getCreateTime = function () {
    return this.createTime;
};

Table.prototype.getMultiplier = function () {
    return this.multiplier;
};

Table.prototype.getCreatorUid = function () {
    return this.creatorUid;
};

Table.prototype.join = function (player) {
    let joinOk = false;
    for (let i = 0; i < this.players.length; i++) {
        if (this.players[i] == null) {
            this.players[i] = player;
            player.position = i;
            player.resetInTable();
            player.clearWatchTimes();
            joinOk = true;
            break;
        }
    }
    if (joinOk) {
        this.onAddPlayer(player);
        if (!this.getIsPlaying()) {
            player.startGetReadyCountDown(16);
        }
    }
};

Table.prototype.onAddPlayer = function (player) {

};

Table.prototype.beforePlayerRemoved = function (player) {

};

Table.prototype.afterPlayerRemoved = function (player) {

};

Table.prototype.leave = function (player) {
    this.beforePlayerRemoved(player);
    for (let i = 0; i < this.players.length; i++) {
        if (player != null && this.players[i] === player) {
            player.clearWatchTimes();
            player.clearReady();
            player.resetInTable();
            player.position = -1;
            this.players[i] = null;
            return;
        }
    }
    this.afterPlayerRemoved(player);
};

Table.prototype.broadCast = function (route, msg) {
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null) {
            player.push(route, msg);
        }
    }
};

Table.prototype.broadCastWithout = function (route, msg, uid) {
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && player.getUid() !== uid) {
            player.push(route, msg);
        }
    }
};

Table.prototype.isValid = function () {
    return this.creatorUid === 0 || this.getNumOfPlayers() > 0;
};

Table.prototype.getNumOfSparePosition = function () {
    return this.maxPlayers - this.getNumOfPlayers();
};

Table.prototype.findPlayer = function (frontendId, sessionId) {
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && player.frontendId === frontendId && player.sessionId === sessionId) {
            return player;
        }
    }
    return null;
};

Table.prototype.getNumOfPlayers = function () {
    let num = 0;
    this.players.forEach(function (player) {
        if (player != null) {
            num = num + 1;
        }
    });
    return num;
};

Table.prototype.getNumOfSeats = function () {
    return this.players.length;
};

Table.prototype.findPlayerByUid = function (uid) {
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && player.getUid() === uid) {
            return player;
        }
    }
    return null;
};

Table.prototype.getFee = function () {
    return this.room.fee;
};

Table.prototype.checkGameStart = function () {
    let self = this;
    if (this.getIsPlaying()) {
        return;
    }
    let numOfReadyPlayers = this.getNumOfReadyPlayers();
    if (numOfReadyPlayers === this.getNumOfSeats()) {
        setImmediate(function () {
            self.start();
        });
        return;
    }
    if (numOfReadyPlayers >= 2 && this.lastReadyPlayerTime > 0 &&
        DateUtil.getIntervalSec(this.lastReadyPlayerTime) > 4) {
        setImmediate(function () {
            self.start();
        });
    }
};

Table.prototype.checkPlayerTimeout = function () {
    if (this.getIsPlaying()) {
        return;
    }
    let invalidPlayers = [];
    for (let i = 0; i < this.players.length; i++) {
        let player = this.players[i];
        if (player != null && player.isGotReadyTimeout() && player.isRobot === 0) {
            invalidPlayers.push(player);
        }
    }
    let self = this;
    if (invalidPlayers.length > 0) {
        invalidPlayers.forEach(function (player) {
            self.kick(player);
        })
    }
};

Table.prototype.beforeStart = function () {
    this.clearUnreadys();
};

Table.prototype.clearUnreadys = function () {
    let unreadys = this.getUnreadyPlayers();
    for (let i = 0; i < unreadys.length; i++) {
        let player = unreadys[i];
        player.addWatchTimes();
        if (player.getWatchTimes() >= 2) {
            this.kick(player);
        }
    }
};

Table.prototype.notifyMessage = function (msg) {
    this.broadCast("onPlayerChat", msg);
};

//TODO refactor here
Table.prototype.kick = function (player) {
    this.broadCast("onPlayerLeave",
        {uid: player.getUid()}, player.getUid());
    pomelo.app.rpc.account.tableRemote.logoutGame(null, {
        frontendId: player.getFrontendId(),
        sessionId: player.getSessionId(),
        gid: this.gid
    }, function () {

    });
    this.leave(player);
};

Table.prototype.tick = function () {
    this.checkGameStart();
    this.checkPlayerTimeout();
};

module.exports = Table;